#'
#'  Define a individual-mapped community
#'
#' @param species a factor vector of species name for all individuals
#' @param x,y a numeric vector contains spatial location of the individuals
#' @param valid_check a logical flag to check the validation of spatial coordination and species name
#' @param traits a dataframe with individual-based traits, such as DBH, alive et al.
#' 
#' @details
#' The community object is just a simple warp of a data frame with columns named 
#' 'species', 'x', 'y', plus some traits columns is available.
#' 
#' There is only one aditional  information about plot range stored in 'plotdim' 
#' attribute of the community object.
#'
#' The community is considered as valid, if
#' 
#'1. The x, y columns should not contain missing values
#'
#'2. all columns with numeric values should not contain infinite numbers
#'
#'3. all columns moust have the same length.
#'
#'4. spatial locations of individuals can not be overlapped.
#'
#'5. The Species columns can have NA to indicate unidentified yet individuals
#'
#'6. all of individuals distributed within the plot.
#'
#' Because each individual can has different types of traits, thus there is no general validation proceduces
#' for each given trait column. However, there are possible some validation check for the following traits:
#' 
#' \itemize{
#'  \item dbh must be numeric on centimeter scale without NA values.
#'  \item alive 
#' }
#'
#' @return
#' A community object must contain three columns at least:
#' 
#' \itemize{
#' \item species
#' \item x
#' \item y
#' }
#' 
#' And a plot range value in its attribute 'plotdim'.
#' 
#' 
#' 
#' @examples
#' 
#' #create an empty community
#' community(species=character(),x=numeric(),y=numeric(),plotdim=c(1,1))
#' 
#' data(BCI)
#' BCI
#' 
#' sp=paste("sp",1:4,sep="")
#' species=sample(rep(sp,1:4),sum(1:4))
#' plotdim=c(10,8)
#' x=runif(length(species),0,plotdim[1])
#' y=runif(length(species),0,plotdim[2])
#' 
#' com=community(species,x,y,plotdim)
#' 
#' com
#' 
#' plot(com)
#'
#' 
#' com2=community(species=species,x=x,y=y,plotdim=plotdim,traits=data.frame(dbh=runif(length(species),1,10)))
#' 
#' com2
#' 
#' plot(com2)
#' 
#'
#'
#'
#'
#' @export
community=function(species,x,y,plotdim,valid_check=TRUE,traits=NULL){
  #FORMATE CHECK PROCEDUCES
  if(valid_check){
    is_valid_coordinate(x,y,plotdim)
    if(length(species)!=length(x))
      stop("length of species and coordinates is not equal")
  }
  
  if(is.factor(species))                   #remove the empty species left in the levels
    species=as.character(species)
  
  com=data.frame(species=species,x=x,y=y)
  
  com$species=as.factor(as.character(com$species))
  
  if(!is.null(traits)){
    if(!is.data.frame(traits)) stop("the given traits is not a data frame")
    
    if(dim(traits)[1]!=length(x)) stop("the number of trait row does not equal to the number of individuals")
    
    tnames=colnames(traits)
    if("dbh" %in% tnames){
      if(!is.numeric(traits$dbh))
        warning("Values in the DBH column of traits are not numeric")
    }
    #TODO check validation for each trait type
    com=cbind(com,traits)    #combine the trait columns
  }
    
  
  attr(com,"plotdim")=plotdim
  class(com)=c("community",class(com))
  return(com)
}

#' @export
print.community=function(com,valid_check=TRUE){
  plotdim=attr(com,"plotdim")
  cat(paste("A individual-mapped community with",total_abundance(com),"individuals, \n"))
  cat(paste(total_richness(com),"species in a",plotdim[1],"*",plotdim[2],"rectangle region \n"))
  tnames=get_trait_names(com)
  if(length(tnames)!=0){
    cat(paste(paste(tnames,collapse=","),ifelse(length(tnames)==1,"is","are"),"also measured for each individuals \n"))
  }
  #check the coordination of the plot again
  if(valid_check)
    is_valid_coordinate(com$x,com$y,plotdim)
}
